﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;
using System.Reflection;

public class BindManage:BaseObject
{
    private static BindManage self;

    private BaseObject _callbackTable;
    private BaseObject _arrSceneProp;

    private CallBackGroup _sceneobjGroup;

    //视图回调组数组
    protected Hashtable _viewCallBackGroup = new Hashtable();
    //表格回调组数组
    protected Hashtable _recCallBackGroup = new Hashtable();

    //public delegate void addfunc(params object[] val);
    //public event addfunc _addfunc;

    //public delegate void removefunc(params object[] val);
    //public event removefunc _removefunc;

    //public delegate void updatefunc(params object[] val);
    //public event updatefunc _updatefunc;

    public static BindManage getInstance()
    {
        if (self == null)
        {
            self = new BindManage();
        }
        return self;
    }

    public BindManage()
    {
        Init();
    }

    private void Init()
    {
        _callbackTable = new BaseObject();
        _sceneobjGroup = new CallBackGroup();
        _arrSceneProp = new BaseObject();
    }

    /// <summary>
    /// 绑定场景属性
    /// </summary>
    /// <param name="scene"></param>
    /// <param name="PropertiesName"></param>
    /// <param name="addfunc"></param>
    /// <param name="removefunc"></param>
    /// <returns></returns>
    public int BindSceneProperty(Scene scene, string PropertiesName, ArrayList pList)
    {
        ArrayList pArray = new ArrayList();
        if (pList == null)
        {
            pArray.Add(PropertiesName);
            pArray.Add(scene.GetProperties(PropertiesName));
        } 
        else
        {
            pArray.Add(PropertiesName);
            pArray.Add(scene.GetProperties(PropertiesName));
            pArray.Add(pList);
        }

        CallBack callback = new CallBack(addfunc, null,pArray);

        if (scene.CheckProperties(PropertiesName))
        {
            callback.Call(true);
        }

        if (!_arrSceneProp.CheckProperties(PropertiesName))
        {
            _arrSceneProp.HandleProperties(PropertiesName, new CallBackGroup());
        }

        return (_arrSceneProp.GetProperties(PropertiesName) as CallBackGroup).Add(callback);
    }
    public int BindSceneProperty(Scene scene, string PropertiesName)
    {
        return BindSceneProperty(scene, PropertiesName,null);
    }

    /// <summary>
    /// 绑定场景对象属性
	/// 只有场景中对象才能使用该方法，视图中对象不可使用 
    /// </summary>
    /// <param name="Obj"></param>
    /// <param name="PropertiesName"></param>
    /// <returns></returns>
    public int BindPropInSceneObj(ObjectData Obj, string PropertiesName, ArrayList pList)
    {
        ArrayList pArray = new ArrayList();
        if (pList == null)
        {
            pArray.Add(PropertiesName);
            pArray.Add(Obj.GetPropertiesEx(PropertiesName));
        }
        else
        {
            pArray.Add(PropertiesName);
            pArray.Add(Obj.GetPropertiesEx(PropertiesName));
            pArray.Add(pList);
        }

        CallBack callback = new CallBack(addfunc, null,pArray);

        if (Obj.CheckProperties(PropertiesName))
        {
            callback.Call(true);
        }

        string objKey = Obj.ObjKey;
        //添加对象对应的属性回调表
        if (!_callbackTable.CheckProperties(objKey))
        {
            _callbackTable.HandleProperties(objKey, new BaseObject());
        }
        BaseObject arrBindProp = (BaseObject)_callbackTable.GetProperties(objKey);
        
        //添加对应属性的回调	
        if (!arrBindProp.CheckProperties(PropertiesName))
        {
            arrBindProp.HandleProperties(PropertiesName, new CallBackGroup());
        }
        CallBackGroup callbackgroup = (CallBackGroup)arrBindProp.GetProperties(PropertiesName);

        return callbackgroup.Add(callback);
    }
    public int BindPropInSceneObj(ObjectData Obj, string PropertiesName)
    {
        return BindPropInSceneObj(Obj, PropertiesName, null);
    }

    /// <summary>
    /// 绑定视图对象属性
	/// 只有视图中对象才能使用该方法，场景对象不可使用 
    /// </summary>
    /// <param name="viewObj"></param>
    /// <param name="objKey"></param>
    /// <param name="PropertiesName"></param>
    /// <returns></returns>
    public int BindPropInViewObj(View viewObj, string objKey, string PropertiesName, ArrayList pList)
    {
        ArrayList pArray = new ArrayList();
        //视图中对象的属性绑定，属于二次绑定，对象一定能取到
        ObjectData Obj = (ObjectData)viewObj.GetPropertiesEx(objKey);
        if (pList == null)
        {
            pArray.Add(PropertiesName);
            pArray.Add(Obj.GetPropertiesEx(PropertiesName));
        }
        else
        {
            pArray.Add(PropertiesName);
            pArray.Add(Obj.GetPropertiesEx(PropertiesName));
            pArray.Add(pList);
        }

        CallBack callback = new CallBack(addfunc, null, pArray);
		
		//属性存在先回调一次
		if(Obj.CheckProperties(PropertiesName))
		{
			callback.Call(true);
		}
		
		//先检查是否有该视图的回调
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++	
		//添加对象对应的属性回调表
		string viewKey		=	viewObj.ObjKey;
		
		if (!_callbackTable.CheckProperties(viewKey))
		{
			_callbackTable.HandleProperties(viewKey , new BaseObject());
		}
		BaseObject arrBindObj	= (BaseObject)_callbackTable.GetProperties(viewKey);
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		//添加对应视图对象的回调表
		if (!arrBindObj.CheckProperties(objKey))
		{
			arrBindObj.HandleProperties(objKey , new BaseObject());
		}
		BaseObject arrBindObjProp	= (BaseObject)arrBindObj.GetProperties(objKey);
		
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		//添加对应属性的回调					
		if(!arrBindObjProp.CheckProperties(PropertiesName))
		{				
			arrBindObjProp.HandleProperties(PropertiesName,new CallBackGroup());
		}
        CallBackGroup callbackgroup = (CallBackGroup)arrBindObjProp.GetProperties(PropertiesName);	
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
					
		return callbackgroup.Add(callback);				
	}
    public int BindPropInViewObj(View viewObj, string objKey, string PropertiesName)
    {
        return BindPropInViewObj(viewObj, objKey, PropertiesName, null);
    }

    public int BindView(Scene scene, int viewid, object mainClass, string addMethod, string removeMethod,string updateMethod)
    {
        if (null == _viewCallBackGroup[viewid])
		{
			_viewCallBackGroup[viewid] = new CallBackGroup();
		}

        ArrayList add_pList = new ArrayList();
        ArrayList remove_pList = new ArrayList();
        ArrayList update_pList = new ArrayList();
        if (addMethod != "")
        {
            add_pList.Add(mainClass);
            add_pList.Add(addMethod);
        }
        if (removeMethod != "")
        {
            remove_pList.Add(mainClass);
            remove_pList.Add(removeMethod);
        }
        if (updateMethod != "")
        {
            update_pList.Add(mainClass);
            update_pList.Add(updateMethod);
        }
		
		CallBack callback	=	new CallBack(addfunc,removefunc,new ArrayList(),new ArrayList(),updatefunc,new ArrayList());

        ArrayList arr = new ArrayList();
        arr.Add(viewid);
        arr.Add(add_pList);
        arr.Add(remove_pList);
        arr.Add(update_pList);
        arr.Add(callback);
		//遍历当前视图及视图中的数据
		scene.getDataForEach(eachFunc,arr);

		return (_viewCallBackGroup[viewid] as CallBackGroup).Add(callback);	
    }

    private static void eachFunc(string propName,object val,ArrayList arr)
    {
        uint viewid = (uint)arr[0];
        if(val is View  && (val as View)._nViewId == viewid)
		{		
			(val as View).getDataForEach(eachfunc,arr);
		}
    }

    private static void eachfunc(string propName, object val,ArrayList arr)
    {
        if (val is ViewObject)
        {
            ArrayList addarr = new ArrayList(3);
            ArrayList add_pList = (ArrayList)arr[1];
            addarr.Add(propName);
            addarr.Add(val);
            addarr.Add(add_pList);
            ArrayList removearr = new ArrayList(3);
            ArrayList remove_pList = (ArrayList)arr[2];
            removearr.Add(propName);
            removearr.Add(val);
            removearr.Add(remove_pList);
            ArrayList updatearr = new ArrayList(3);
            ArrayList update_pList = (ArrayList)arr[3];
            updatearr.Add(propName);
            updatearr.Add(val);
            updatearr.Add(update_pList);

            CallBack callback = (CallBack)arr[4];
            callback._args = addarr;
            callback.remove_args = removearr;
            callback.update_args = updatearr;

            callback.Call(true);
        }
    }


    public int BindRecord(Scene scene,string recName,object mainClass, string addMethod,string removeMethod)
	{
        if (null == _recCallBackGroup[recName])
        {
            _recCallBackGroup[recName] = new CallBackGroup();
        }

        ArrayList add_pList = new ArrayList();
        ArrayList remove_pList = new ArrayList();
        if (addMethod != "")
        {
            add_pList.Add(mainClass);
            add_pList.Add(addMethod);
        }

        if (removeMethod != "")
        {
            remove_pList.Add(mainClass);
            remove_pList.Add(removeMethod);
        }
        

        CallBack callback = new CallBack(addfunc, removefunc, new ArrayList(),new ArrayList());

        int index = (_recCallBackGroup[recName] as CallBackGroup).CheckSame(callback);

        if (index < 0)
        {
            index = (_recCallBackGroup[recName] as CallBackGroup).Add(callback);
        }
        else
        {
            Console.WriteLine("重复绑定,BindRecord {0}", recName);
        }

        if (scene.CheckProperties(recName))
        {
            Record record = scene.GetRecordEx(recName);
            int tSize = record.recArr.Count;

            for (int i = 0; i < tSize; i++)
            {
                ArrayList addarr = new ArrayList(3);
                addarr.Add(i);
                addarr.Add(record.recArr[i]);
                addarr.Add(add_pList);

                ArrayList removearr = new ArrayList(3);
                removearr.Add(i);
                removearr.Add(record.recArr[i]);
                removearr.Add(remove_pList);

                callback._args = addarr;
                callback.remove_args = removearr;

                callback.Call(true);
            }
        }
        return index;
    }

    /// <summary>
    /// 绑定特定属性到特定类的指定方法 
    /// </summary>
    /// <param name="Obj">特定对象上</param>
    /// <param name="PropertiesName">属性</param>
    /// <param name="mainClass">类</param>
    /// <param name="method">方法</param>
    /// <returns></returns>
    public int BindProp(ObjectData Obj, string PropertiesName, object mainClass, string method)
	{
        ArrayList pList = new ArrayList();
        pList.Add(mainClass);
        pList.Add(method);

        int index = -1;
		
		if(Obj == null)
		{
			return index;
		}

        if (Obj is SceneObject || Obj is View)
        {
            index = BindPropInSceneObj(Obj, PropertiesName, pList);
        }
        else if (Obj is ViewObject)
        {
            index = BindPropInViewObj(Obj.parent as View, Obj.ObjKey, PropertiesName, pList);
        }
        else if (Obj is Scene)
        {
            index = BindSceneProperty(Obj as Scene, PropertiesName, pList);
        }
		return index;
	}

    /// <summary>
    /// 反射机制
    /// 回调方法,val分别为：PropertiesName,PropertiesValue,[(object)类,(string)方法];
    /// </summary>
    /// <param name="val"></param>
    public static void addfunc(params object[] val)
	{
        ArrayList mainArr = (ArrayList)val[0];
        ArrayList arr = (ArrayList)mainArr[2];
        //反射
        MethodInfo info = null;
        object mainClass = (object)arr[0];
        //传入类的类型 
        Type type = mainClass.GetType();
        //得到调用类的方法 
        info = type.GetMethod((string)arr[1]);
        //执行方法
        info.Invoke(mainClass, new object[] { arr[1] });
	}
    /// <summary>
    /// 回调方法,val分别为：PropertiesName,PropertiesValue,[(object)类,(string)方法];
    /// </summary>
    /// <param name="val"></param>
    private static void removefunc(params object[] val)
    {
        ArrayList mainArr = (ArrayList)val[0];
        ArrayList arr = (ArrayList)mainArr[2];
        //反射
        MethodInfo info = null;
        object mainClass = (object)arr[0];
        //传入类的类型 
        Type type = mainClass.GetType();
        //得到调用类的方法 
        info = type.GetMethod((string)arr[1]);
        //执行方法
        info.Invoke(mainClass, new object[] { arr[1] });
    }

    /// <summary>
    /// 回调方法,val分别为：PropertiesName,PropertiesValue,[(object)类,(string)方法];
    /// </summary>
    /// <param name="val"></param>
    private static void updatefunc(params object[] val)
    {
        ArrayList mainArr = (ArrayList)val[0];
        ArrayList arr = (ArrayList)mainArr[2];
        //反射
        MethodInfo info = null;
        object mainClass = (object)arr[0];
        //传入类的类型 
        Type type = mainClass.GetType();
        //得到调用类的方法 
        info = type.GetMethod((string)arr[1]);
        //执行方法
        info.Invoke(mainClass, new object[] { arr[1] });
    }

    public void CallBind(ObjectData Obj,string PropertiesName, object PropertiesValue,Boolean isAdd)
	{
		//分类处理			
		if(Obj is Scene)
		{	
			//场景				
			CallSceneBind(Obj,PropertiesName,PropertiesValue,isAdd);	
		}
		
		else if(Obj is SceneObject)
		{
			//场景对象
			//肯定是属性变化,属性只有变化，没有删除
			CallSceneObjectBind(Obj as SceneObject,PropertiesName,PropertiesValue);				
		}
		else if(Obj is View)
		{			
			//视图有两种，一种属性，一种是对象
			if(PropertiesValue is ObjectData)
			{
				//视图
				CallView(Obj as View,PropertiesName,PropertiesValue,isAdd);
			}
			else
			{
				CallSceneObjectBind(Obj as ObjectData,PropertiesName,PropertiesValue);	
			}
		}
		else if(Obj is ViewObject)
		{			
			//视图对象
			//肯定是属性变化,属性只有变化，没有删除
			CallViewObjct(Obj as ViewObject,PropertiesName,PropertiesValue);
		}			
	}

    public void CallSceneBind(ObjectData Obj,string PropertiesName, object PropertiesValue,Boolean isAdd)
	{
		//场景有四种子对象			
		if(PropertiesValue is SceneObject)
		{
			//场景对象
			_sceneobjGroup.DoCallBack(PropertiesName,PropertiesValue,isAdd);
		}
		else if(PropertiesValue is View)
		{
			//视图
			//视图增加不需要操作
		}
		else if(PropertiesValue is Record)
		{
			//表格
			//表格增加也不需要操作
		}
		else 
		{
			if(!_arrSceneProp.CheckProperties(PropertiesName))
			{
				return ;
			}				
			//场景属性，属性只有变化，没有删除
			(_arrSceneProp.GetProperties(PropertiesName) as CallBackGroup).DoCallBack(PropertiesName,PropertiesValue,true);
		}
	}

    public void CallSceneObjectBind(ObjectData Obj,string PropertiesName, object PropertiesValue)
	{
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++	
		//检查对象对应的属性回调表
		string objKey		=	Obj.ObjKey;
		
		if (!_callbackTable.CheckProperties(objKey))
		{
			return ;
		}
		BaseObject arrBindProp	= (BaseObject)_callbackTable.GetProperties(objKey);
		
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		//检查对应属性				
		if(!arrBindProp.CheckProperties(PropertiesName))
		{
			return;
		}
        CallBackGroup callbackgroup = (CallBackGroup)arrBindProp.GetProperties(PropertiesName);	
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		callbackgroup.DoCallBack(PropertiesName,PropertiesValue,true,false);
	}

    public void CallView(View Obj,string PropertiesName, object PropertiesValue,Boolean isAdd)
	{
		//场景有四种子对象			
		if(PropertiesValue is ViewObject)
		{
			//视图对象
			if(null !=	_viewCallBackGroup[Obj._nViewId])
			{
				(_viewCallBackGroup[Obj._nViewId] as CallBackGroup).DoCallBack(PropertiesName,PropertiesValue,isAdd,false);
			}
		}
		else 
		{
			//视图属性，属性只有变化，没有删除
			//暂不考虑
		}
	}

    public void CallViewObjct(ViewObject Obj,string PropertiesName, object PropertiesValue)
	{
		//先检查是否有该视图的回调
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++	
		//添加对象对应的属性回调表
		string viewKey		=	(Obj.parent as View).ObjKey;
			
		if (!_callbackTable.CheckProperties(viewKey))
		{
			return;
		}
		BaseObject arrBindObj	=(BaseObject)_callbackTable.GetProperties(viewKey);
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		//添加对应视图对象的回调表
		if (!arrBindObj.CheckProperties(Obj.ObjKey))
		{
			return;
		}
		BaseObject arrBindObjProp	= (BaseObject)arrBindObj.GetProperties(Obj.ObjKey);
		
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		//添加对应属性的回调					
		if(!arrBindObjProp.CheckProperties(PropertiesName))
		{				
			return;
		}
        CallBackGroup callbackgroup = (CallBackGroup)arrBindObjProp.GetProperties(PropertiesName);
		callbackgroup.DoCallBack(PropertiesName,PropertiesValue,true);
	}

    public void CallRecord(Record Obj,int row,object PropertiesValue,Boolean isAdd)
	{
		string PropertiesName	=	row.ToString();
		//场景有四种子对象			
		if(PropertiesValue is Array)
		{
			//视图对象
			if(null !=	_recCallBackGroup[Obj.recName])
			{
				(_recCallBackGroup[Obj.recName] as CallBackGroup).DoCallBack(PropertiesName,PropertiesValue,isAdd);
			}
		}
		else 
		{
			//视图属性，属性只有变化，没有删除
			//暂不考虑
		}
	}

	public void UnbindSceneProperty(string PropertiesName,int index)
	{
		if(_arrSceneProp.CheckProperties(PropertiesName))
		{
			(_arrSceneProp.GetProperties(PropertiesName) as CallBackGroup).Remove(index);
		}
		index = -1;
	}

    private int UnbindPropInSceneObj(SceneObject Obj,string PropertiesName,int index)
	{
		//添加对象对应的属性回调表
		string objKey		=	Obj.ObjKey;
		
		if (!_callbackTable.CheckProperties(objKey))
		{
			return -1;
		}
		BaseObject arrBindProp	= (BaseObject)_callbackTable.GetProperties(objKey);
		
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		//添加对应属性的回调					
		if(!arrBindProp.CheckProperties(PropertiesName))
		{
			return -1;
		}
		CallBackGroup callbackgroup	=	(CallBackGroup)arrBindProp.GetProperties(PropertiesName);	
		
		callbackgroup.Remove(index);
		return -1;
	}

     private int UnbindPropInViewObj(View viewObj,string objKey,string PropertiesName,int index)
	{
		//添加对象对应的属性回调表
		string viewKey		=	viewObj.ObjKey;
		
		if (!_callbackTable.CheckProperties(viewKey))
		{
			_callbackTable.HandleProperties(viewKey , new BaseObject());
		}
		BaseObject arrBindObj	= (BaseObject)_callbackTable.GetProperties(viewKey);
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		//添加对应视图对象的回调表
		if (!arrBindObj.CheckProperties(objKey))
		{
			return -1;
		}
		BaseObject arrBindObjProp	= (BaseObject)arrBindObj.GetProperties(objKey);
		
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
		//添加对应属性的回调					
		if(!arrBindObjProp.CheckProperties(PropertiesName))
		{				
			return -1;
		}			
		CallBackGroup callbackgroup	=	(CallBackGroup)arrBindObjProp.GetProperties(PropertiesName);	
		
		callbackgroup.Remove(index);
		return -1;
	}

    /// <summary>
    /// 解除绑定
    /// </summary>
    /// <param name="Obj"></param>
    /// <param name="PropertiesName"></param>
    /// <param name="index"></param>
    /// <returns></returns>
    public int UnbindProp(ObjectData Obj,string PropertiesName,int index)
	{
        if ( -1 == index)
        {
            return -1;
        }
		if(Obj is SceneObject)
		{
			UnbindPropInSceneObj(Obj as SceneObject,PropertiesName,index);
		}
		else if(Obj is ViewObject)
		{
			UnbindPropInViewObj(Obj.parent as View,Obj.ObjKey,PropertiesName,index);
		}
		else if(Obj is Scene)
		{
			UnbindSceneProperty(PropertiesName,index);
		}		
		return -1;
	}
    public int UnbindProp(ObjectData Obj, string PropertiesName)
    {
        return -1;
    }

    /// <summary>
    /// 删除所有绑定
    /// </summary>
    /// <param name="Obj"></param>
    /// <param name="PropertiesName"></param>
    public void UnbindPropAll(ObjectData Obj,string PropertiesName)
	{
		if(Obj is SceneObject)
		{
			UnbindPropInSceneObjAll(Obj as SceneObject,PropertiesName);
		}
		else if(Obj is ViewObject)
		{
			UnbindPropInViewObjAll(Obj.parent as View,Obj.ObjKey,PropertiesName);
		}
		else if(Obj is Scene)
		{
			UnbindScenePropertyAll(PropertiesName);
		}	
	}

    private void UnbindPropInSceneObjAll(SceneObject Obj,string PropertiesName)
	{
		//添加对象对应的属性回调表
		string objKey		=	Obj.ObjKey;
		
		if (_callbackTable.CheckProperties(objKey))
		{
			_callbackTable.DeleteProperties(objKey);
		}					
	}

    private void UnbindPropInViewObjAll(View viewObj,string objKey,string PropertiesName)
	{
		string viewKey		=	viewObj.ObjKey;
		
		if (_callbackTable.CheckProperties(viewKey))
		{
			BaseObject arrBindObj	= (BaseObject)_callbackTable.GetProperties(viewKey);
			//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			//删除viewobj关联所有属性绑定
			if (!arrBindObj.CheckProperties(objKey))
			{
				arrBindObj.DeleteProperties(objKey);
			}
		}
	}

    public void UnbindScenePropertyAll(string PropertiesName)
	{
		if(_arrSceneProp.CheckProperties(PropertiesName))
		{
			_arrSceneProp.DeleteProperties(PropertiesName);
		}
	}


    public int UnbindRecord(string recName,int index)
	{
		if (null == _recCallBackGroup[recName] || -1 == index )
		{
			return -1;
		}
		(_recCallBackGroup[recName] as CallBackGroup).Remove(index);
		return -1;
	}

    public int UnbindView(int viewid,int index)
	{
		if( -1 == index)
		{
			return -1;
		}
		if (null == _viewCallBackGroup[viewid])
		{
			return -1;
		}
		(_viewCallBackGroup[viewid] as CallBackGroup).Remove(index);
		return -1;
	}



}
